package jp.tomorrowkey.intellij.injectlogtag;
import com.intellij.codeInsight.CodeInsightActionHandler;
import com.intellij.codeInsight.generation.actions.BaseGenerateAction;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationType;
import com.intellij.notification.Notifications;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.CaretModel;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
/**
* @author tomorrowkey
*/
public class InjectLogTagAction extends BaseGenerateAction {
public InjectLogTagAction() {
super(new GenerateInjectLogHandler());
}
static class GenerateInjectLogHandler implements CodeInsightActionHandler {
@Override
public void invoke(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile psiFile) {
final Document document = editor.getDocument();
CaretModel caretModel = editor.getCaretModel();
final PsiClass psiClass = getPsiClass(editor, psiFile);
if (psiClass == null) {
warning("Inject LOG_TAG", "Caret must be in a class.");
return;
}
if (findFieldByName(psiClass, "LOG_TAG") != null) {
warning("Inject LOG_TAG", "LOG_TAG is already in the class.");
return;
}
int currentLine = caretModel.getLogicalPosition().line;
int line = findPositionOfClassDeclarationLine(document, currentLine);
if (line == 0) {
warning("Inject LOG_TAG", "Not found the position of class declaration.");
return;
}
caretModel.moveToLogicalPosition(new LogicalPosition(line + 1, 0));
final int offset = caretModel.getOffset();
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
String code = generateLogTagCode(psiClass);
document.insertString(offset, "\n");
document.insertString(offset, code);
document.insertString(offset, "\n");
}
});
}
private PsiField findFieldByName(PsiClass psiClass, String fieldName) {
PsiField[] fields = psiClass.getFields();
for (PsiField field : fields) {
if (field.getName().equals(fieldName)) {
return field;
}
}
return null;
}
private int findPositionOfClassDeclarationLine(Document document, int currentLine) {
String documentText = document.getCharsSequence().toString();
for (int i = currentLine; i >= 0; i--) {
int lineStartOffset = document.getLineStartOffset(i);
int lineEndOffset = document.getLineEndOffset(i);
String line = documentText.subSequence(lineStartOffset, lineEndOffset).toString();
if (line.indexOf(" class ") >= 0) {
return i;
}
}
return 0;
}
private PsiClass getPsiClass(Editor editor, PsiFile psiFile) {
int offset = editor.getCaretModel().getOffset();
PsiElement psiElement = psiFile.findElementAt(offset);
PsiClass psiClass = PsiTreeUtil.getParentOfType(psiElement, PsiClass.class);
return psiClass;
}
private String generateLogTagCode(PsiClass psiClass) {
return String.format("private static final String LOG_TAG = %s.class.getSimpleName();", psiClass.getName());
}
private void warning(String title, String message) {
Notification notification = new Notification("inject-log-tag", title, message, NotificationType.WARNING);
Notifications.Bus.notify(notification);
}
@Override
public boolean startInWriteAction() {
return false;
}
}
}